package icasue.net.socket.driver.providers;

import icasue.net.base.annotations.NotNull;
import icasue.net.socket.driver.CommandDriver;
import icasue.net.socket.exception.ProtocolUnSupportException;
import icasue.net.socket.driver.event.EventCommandDriver;
import icasue.net.socket.driver.mdc.MDCommandDriver;
import icasue.net.socket.driver.providers.support.BasicEventCommandDriverProvider;
import icasue.net.socket.driver.providers.support.BasicMDCommandDriverProvider;
import icasue.net.protocol.carfun.commands.Command;
import icasue.net.protocol.carfun.commands.EventCommand;
import icasue.net.protocol.carfun.commands.MDCommand;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: Qiao Hang
 * @CreateDate: 2021/3/24 上午9:58
 * @UpdateDate:
 * @Description:
 */
public class CommandDriverManager {

    /* MDCDriverProviders */
    private static volatile List<MDCommandDriverProvider> mdCommandDriverProviders = new ArrayList<>();

    /* BizCDriverProviders */
    private static volatile List<EventCommandDriverProvider> eventCommandDriverProviders = new ArrayList<>();

    static {
        //Fulling a MDCommandDriverProvider, this Provider manage MDCommandDrivers which supported by system,
        // such as MDClient, MDChannel.
        mdCommandDriverProviders.add(new BasicMDCommandDriverProvider());
        //Fulling a EventCommandDriverProvider, this Provider manage EventCommandDrivers which supported by system,
        // such as EventChannel.
        eventCommandDriverProviders.add(new BasicEventCommandDriverProvider());
    }


    /**
     * parse command.
     * @param command
     * @return
     * @throws ProtocolUnSupportException
     */
    public static MDCommand parseMDCommand(@NotNull String command) throws ProtocolUnSupportException {
        for (MDCommandDriverProvider mdCommandDriverProvider : mdCommandDriverProviders) {
            for (MDCommandDriver mdCommandDriver : mdCommandDriverProvider.mdCommandDrivers) {
                Command mdCommandSupport = mdCommandDriver.commandSupport(command);
                if(mdCommandSupport != null){
                    return (MDCommand)mdCommandSupport;
                }
            }
        }
        throw new ProtocolUnSupportException("Protocol MDCommand["+command+"] UnSupported.");
    }

    public static EventCommand parseEventCommand(@NotNull String command) throws ProtocolUnSupportException {
        for (EventCommandDriverProvider eventCommandDriverProvider : eventCommandDriverProviders) {
            for (EventCommandDriver eventCommandDriver : eventCommandDriverProvider.eventCommandDrivers) {
                Command eventCommandSupport = eventCommandDriver.commandSupport(command);
                if(eventCommandSupport != null){
                    return (EventCommand)eventCommandSupport;
                }
            }
        }
        throw new ProtocolUnSupportException("Protocol EventCommand["+command+"] UnSupported.");
    }

    /**
     * Choose a command driver.
     * @param command
     * @return
     */
    public static MDCommandDriver chooseMDDriver(@NotNull Command command) throws ProtocolUnSupportException {
        for (MDCommandDriverProvider mdCommandDriverProvider : mdCommandDriverProviders) {
            for (MDCommandDriver mdCommandDriver : mdCommandDriverProvider.mdCommandDrivers) {
                CommandDriver commandDriver = mdCommandDriver.driverSupport(command);
                if(commandDriver != null){
                    return (MDCommandDriver)commandDriver;
                }
            }
        }
        throw new ProtocolUnSupportException("Protocol MDCommand["+command.getCommand()+"] has no supported Driver.");
    }


    public static EventCommandDriver chooseEventDriver(@NotNull Command command) throws ProtocolUnSupportException {
        for (EventCommandDriverProvider eventCommandDriverProvider : eventCommandDriverProviders) {
            for (EventCommandDriver eventCommandDriver : eventCommandDriverProvider.eventCommandDrivers) {
                CommandDriver commandDriver = eventCommandDriver.driverSupport(command);
                if(commandDriver != null){
                    return (EventCommandDriver)commandDriver;
                }
            }
        }
        throw new ProtocolUnSupportException("Protocol EventCommand["+command.getCommand()+"] has no supported Driver.");
    }
}
